package com.car.utils;

import com.car.config.DataSourceConfig;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.Log4JLogger;

import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * JDBC工具类
 */
public class JDBCUtils {
    //日志
    private static final Log log = LogFactory.getLog(JDBCUtils.class);

    /**
     *创建预编译对象
     *
     * @param sql sql
     * @param params sql参数
     * @return 预编译对象
     */

    public static PreparedStatement createPreparedStatement(String sql, Object ...params)throws Exception{
       //获取连接对象
        Connection connection = DataSourceConfig.getConnection();
        //获取预编译对象PreparedStatement  放入sql 比如select * from t_user where id =?
        PreparedStatement ps = connection.prepareStatement(sql);
        //获取参数元数据
        ParameterMetaData parameterMetaData = ps.getParameterMetaData();
        //获取字符串需要的参数个数 => 问号个数
        int parameterCount = parameterMetaData.getParameterCount();
        //问号个数和sql参数的个数长度要一直
        if (params.length != parameterCount){
            log.info("JDBCUtils => SQL参数不一致，sql=>" + ps +",参数："+ Arrays.toString(params));
            throw new RuntimeException("SQL参数不一致");
        }
        //判断什么情况下赋值
        if (params.length > 0){
            for (int i = 1; i <= params.length ; i++) {
                ps.setObject(i,params[i - 1]);
            }
        }
        //日志信息
        log.info("JDBC=>" + ps);
        return ps;
    }

    /**
     * @param sql DML DDL 语句
     * @param params 参数
     * @throws Exception 异常
     */
    public static int update (String sql,Object...params) throws Exception{
        //创建预编译对象
        PreparedStatement ps = createPreparedStatement(sql,params);
        //执行SQL
       int i = ps.executeUpdate();
       log.info("影响记录数：" + i);
       //关闭资源
        close(ps,ps.getConnection());
        return i;
    }

    /**
     * 根据查询数据 封装成对应实体类
     *
     * 根据查询数据 封装
     * @param sql sql
     * @param c 类型
     * @param params 参数
     * @return 实体类
     * @param <T> 泛型T
     * @throws Exception 异常
     */
    public static <T> T query(String sql,Class<T> c ,Object...params) throws Exception{
        //创建预编译对象
        PreparedStatement ps = createPreparedStatement(sql,params);
        //执行SQL
        ResultSet resultSet = ps.executeQuery();
        //获取数据库表字段
        ResultSetMetaData metaData = resultSet.getMetaData();
        //指向记录
        resultSet.next();
        //循环获取字段
        T res = c.getConstructor().newInstance();
        for (int i = 1; i < metaData.getColumnCount(); i++) {
            //参数： 实体类，实体类的字段名，值 底层都是使用set方法
            BeanUtils.setProperty(res,toCovertFiledName(metaData.getColumnName(i)),resultSet.getObject(i));
        }
        System.out.println();
        return null;
    }

    public static <T>List<T> queryList(String sql,Class<T> c,Object...params) throws Exception{
        //创建预编译对象
        PreparedStatement ps = createPreparedStatement(sql,params);
        //执行SQL
        ResultSet resultSet = ps.executeQuery();
        //获取数据库表字段"id" "name" "age" "gender" "work_id" => "workId" "salary"
        ResultSetMetaData metaData = resultSet.getMetaData();
        //创建List集合
        List<T>list = new ArrayList<>();
        //循环遍历获取实体类对象 并且放入集合中
        while (resultSet.next()){
            //循环获取字段的值
            T res = c.getConstructor().newInstance();
            for (int i = 1; i < metaData.getColumnCount(); i++) {
                //参数： 实体类，实体类的字段名，值 底层都是使用set方法
                BeanUtils.setProperty(res,toCovertFiledName(metaData.getColumnName(i)),resultSet.getObject(i));
            }
            list.add(res);
        }
        //关闭资源
        close(resultSet,ps,ps.getConnection());
        return list;
    }

    @SafeVarargs
    public static <E extends AutoCloseable> void close(E...es)throws Exception{
        for (E e : es){
            if (e !=null){
                e.close();
            }
        }
    }

    public static String toCovertFiledName(String filedName){
        if (!filedName.contains("_")){
            return filedName;
        }
        StringBuilder sb = new StringBuilder();
        String[] split = filedName.split("_");
        sb.append(split[0]);
        for (int i = 1; i < split.length; i++) {
            char c = (char) (split[i].charAt(0)-32);
            sb.append(c).append(split[i].substring(1));
        }
        return sb.toString();
    }
}

